/**
 * 
 * 广州锐鹏计算机科技有限公司（www.ruipengkj.com）
 * 
 * 
 * Copyright (c) 2011-2012 RUIPENGKJ.Co.Ltd. All rights reserved.
 * 
 * */
package com.ruipengkj.commons.base.dao;



import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.ruipengkj.commons.base.query.BaseQuery;
import com.ruipengkj.commons.base.query.PageModel;
import com.ruipengkj.commons.base.query.QueryUtil;
import com.ruipengkj.commons.util.ResultSetMapper;





/**
 * 说明：基础DAO实现类
 * 该类是个抽象类，并继承了HibernateTemplateSupport获得hibernateTemplate
 * 使用hibernateTemplate来操作数据库
 * <br/>作者： 李智深
 * <br/>日期： 2010-2-24
 */
public class BaseDaoSupport<T> extends HibernateTemplateSupport<T> implements BaseDao<T> {

	
	@SuppressWarnings("unchecked")
	public T getById(Class<T> entityClass, Serializable id)
			throws RuntimeException {
		return (T) getHiberanteTemplate().get(entityClass, id) ;
	}

	public void insertOrUpdate(T entity) throws RuntimeException {
		getHiberanteTemplate().saveOrUpdate(entity) ;
	}

	@SuppressWarnings("unchecked")
	public T loadById(Class<T> entityClass, Serializable id)
			throws RuntimeException {
		return (T) getHiberanteTemplate().load(entityClass, id) ;
	}

	public void saveObject(T entity) throws RuntimeException {
		getHiberanteTemplate().save(entity) ;
	}
	
	public Serializable saveObjectRet(T entity) throws RuntimeException {
		return getHiberanteTemplate().save(entity) ;
	}

	public void updateObject(T entity) throws RuntimeException {
		getHiberanteTemplate().update(entity) ;
	}
	
	public void deleteObject(Class<T> entityClass, Serializable id)
	throws RuntimeException {
		getHiberanteTemplate().delete(loadById(entityClass,id)) ;
	}
	
	public void deleteObject(T entity) throws RuntimeException {
		getHiberanteTemplate().delete(entity) ;
	}

	
	public void deleteAllObject(final Class<T> entityName, final Object[] ids)
			throws RuntimeException {
		this.getHiberanteTemplate().execute(new HibernateCallback() {
			
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				if(ids.length > 0) {
					for(int i=0; i<ids.length; i++) {
						session.delete(loadById(entityName,ids[i].toString())) ;
						if(ids.length%20==0) {
							session.flush() ;
							session.clear() ;
						}
					}
				}
				return null;
			}
		}) ;
	}
	
	
	@SuppressWarnings("unchecked")
	public List<Object> findByProperty(final String property, final String clazz, final String whereHQL,final Object[] param) throws RuntimeException {
		
		return (List<Object>) this.getHiberanteTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				
				String hql = "select " + buildProperty(property) + " from " + clazz + buildWhereHQL(whereHQL);
				Query query = session.createQuery(hql) ;
				
				setQueryParams(query, param) ;
				return query.list() ;
			}
		}) ;
	}
	
	/**
	 * 不根据条件查询
	 */
	@SuppressWarnings("unchecked")
	public List<Object> findByProperty(final String property, final String clazz) throws RuntimeException {
		
		return (List<Object>) this.getHiberanteTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				
				String hql = "select " + buildProperty(property) + " from " + clazz ;
				Query query = session.createQuery(hql) ;
				
				return query.list() ;
			}
		}) ;
	}

	@SuppressWarnings("unchecked")
	public T findSingleEntity(final String hql,final String whereHQL,final List<Object> param) throws RuntimeException {
		
		return (T) getHiberanteTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(hql + buildWhereHQL(whereHQL)) ;
				setQueryParams(query, param) ;
				
				return query.uniqueResult() ;
			}
		}) ;
	}
	
	public Object executeHQL(final String hql,final String setHQL,final String whereHQL,final Object[] param) throws RuntimeException {
		
		return this.getHiberanteTemplate().execute(new HibernateCallback() {
			
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {	
				
				Query query = session.createQuery(hql + buildSetHQL(setHQL) + buildWhereHQL(whereHQL)) ;
				
				setQueryParams(query, param) ;
				
				return query.executeUpdate();
			}
		}) ;
	}
	
	@SuppressWarnings("unchecked")
	public T find(final String hql,final String whereHQL,final List<Object> param,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		return (T) this.getHiberanteTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createQuery(hql + buildWhereHQL(whereHQL) + buildOrderBy(orderby)) ;
				setQueryParams(query, param) ;
				return query.list();
			}
		}) ;
	}
	/**
	 * 根据条件查询，但不排序
	 */
	public T find(final String hql,final String whereHQL,final List<Object> param) throws RuntimeException {
		return this.find(hql, whereHQL, param, null) ;
	}
	/**
	 * 不根据条件查询，但排序
	 */
	public T find(final String hql,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		return this.find(hql, null, null, orderby) ;
	}
	/**
	 * 不排序和条件查询
	 */
	public T find(final String hql) throws RuntimeException {
		return this.find(hql, null, null, null) ;
	}

	
	@SuppressWarnings("unchecked")
	public PageModel<T> getScrollData(final String hql,final String whereHQL, final List<Object> param, final int firstResult,
			final int maxResult,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		return (PageModel)getHiberanteTemplate().execute(new HibernateCallback() {
			
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				PageModel<T> pm = null ;
				List resultList = null ;
						
				Query query = session.createQuery(hql + buildWhereHQL(whereHQL) + buildOrderBy(orderby)) ;
				setQueryParams(query, param) ;
				
				
				if(firstResult!=-1 && maxResult!=-1) query.setFirstResult(firstResult).setMaxResults(maxResult);
				
				resultList = query.list() ;
//				System.out.println(query);
				//统计总记录数
				if(null != resultList && resultList.size()>0) {
					pm = new PageModel<T>() ;
					pm.setResultList(resultList) ;
					pm.setTotalRecord(QueryUtil.getListCount(session, hql + buildWhereHQL(whereHQL),param).intValue()) ;
				}
				return pm;
			}
		}) ;
	}
	/**
	 * 根据条件查询并分页，但不排序
	 */
	public PageModel<T> getScrollData(String hql,final String whereHQL, List<Object> param, int firstResult,
			int maxResult) throws RuntimeException {
		return this.getScrollData(hql, whereHQL, param, firstResult, maxResult, null) ;
	}
	/**
	 * 排序并分页，但不根据条件查询
	 */
	public PageModel<T> getScrollData(String hql, int firstResult,int maxResult,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		return this.getScrollData(hql, null, null, firstResult, maxResult, orderby) ;
	}
	/**
	 * 不排序和条件查询，进行分页
	 */
	public PageModel<T> getScrollData(String hql,int firstResult,int maxResult) throws RuntimeException {
		return this.getScrollData(hql, null, null, firstResult, maxResult, null) ;
	}
	

	/**
	 * 获得查询条件语句
	 * @param whereHQL
	 * @return
	 */
	protected static String buildWhereHQL(String whereHQL) {
		return (null == whereHQL || "".equals(whereHQL.trim()) ? "" :BaseQuery.WHERE+whereHQL) ;
	}
	
	/**
	 * 获得修改条件语句
	 * @param buildSetHQL
	 * @return
	 */
	protected static String buildSetHQL(String setHQL) {
		return (null == setHQL || "".equals(""+setHQL.trim()) ? "" : BaseQuery.SET + setHQL) ;
	}
	
	/**
	 * 设置参数值
	 * @param query
	 * @param param<List>
	 */
	protected static void setQueryParams(Query query,List<Object> param) {
		if(null != param && param.size() > 0) {
			for(int i=0; i<param.size(); i++) {
				query.setParameter(i,param.get(i)) ;
			}
		}
	}
	/**
	 * 设置参数值
	 * @param query
	 * @param param<Object>
	 */
	protected static void setQueryParams(Query query,Object[] param) {
		if(null != param && param.length > 0) {
			for(int i=0; i<param.length; i++) {
				query.setParameter(i,param[i]) ;
			}
		}
	}
	
	/**
	 * 组装order by语句
	 * @param orderby
	 * @return
	 */
	protected static String buildOrderBy(LinkedHashMap<String, String> orderby) {
		StringBuffer sb = new StringBuffer() ;
		
		if(null != orderby && orderby.size() > 0) {
			sb.append(BaseQuery.ORDERBY) ;
			for(String key : orderby.keySet()) {
				sb.append("o.").append(key).append(" ").append(orderby.get(key)).append(",") ;
			}
			sb.deleteCharAt(sb.length() - 1) ;
		}
		return sb.toString() ;
	}

	/**
	 * 组装查询属性
	 * @param property
	 * @return
	 */
	public static String buildProperty(String property) {
		return (null != property && !"".equals(property.trim())? property.trim() : "") ;
	}
	
	/**
	 * <p>
	 * exeSQL方法-执行update/delete等语句.
	 * </p>
	 * <p>
	 * 创建人 IT山人 创建时间 2010-6-21 - 下午08:54:04
	 * </p>
	 * 
	 * @param sql
	 *            待执行的sql语句
	 * @return 操作的记录数量
	 */

	public int executeSQL(final String sql) {
		return (Integer) this.getHiberanteTemplate().execute(new HibernateCallback() {
			Connection connection = null;
			PreparedStatement statement = null;
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				connection = SessionFactoryUtils.getDataSource(
						session.getSessionFactory()).getConnection();
				statement = connection.prepareStatement(sql);
				return statement.executeUpdate();
			}
		}) ;
	}

	/**
	 * <p>
	 * querySQL方法-运行select的查询语句.
	 * </p>
	 * <p>
	 * 创建人 IT山人 创建时间 2010-6-21 - 下午08:55:25
	 * </p>
	 * 
	 * @param sql
	 *            待执行的sql语句
	 * @return List<Object[]> 查询结果集合
	 */
	public List<Object[]> querySQL(final String sql) {
		List<Object[]> resultList = new ArrayList<Object[]>();
		Connection connection = null;
		PreparedStatement statement = null;
		ResultSet rs = null;
		try {
			connection = SessionFactoryUtils.getDataSource(
					this.getHiberanteTemplate().getSessionFactory())
					.getConnection();
			statement = connection.prepareStatement(sql);
			rs = statement.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			int columnCount = rsmd.getColumnCount();
			Object[] objects = new Object[columnCount];
			// 数据库列名
			for (int i = 0; i < columnCount; i++) {
				objects[i] = rsmd.getColumnName(i + 1);
			}
			resultList.add(objects);

			// // 列别名
			// objects = new Object[columnCount];
			// for (int i = 0; i < columnCount; i++) {
			// objects[i] = rsmd.getColumnLabel(i+1);
			// }
			// resultList.add(objects);

			// 数据集合
			while (rs.next()) {
				objects = new Object[columnCount];
				for (int i = 0; i < columnCount; i++) {
					objects[i] = rs.getObject(i + 1);
				}
				resultList.add(objects);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			release(rs, statement, connection);
		}
		return resultList;
	}

	/**
	 * <p>
	 * release方法-资源释放.
	 * </p>
	 * <p>
	 * 创建人 IT山人 创建时间 2010-6-21 - 下午08:52:40
	 * </p>
	 * 
	 * @param rs
	 *            java.sql.ResultSet
	 * @param sta
	 *            java.sql.Statement
	 * @param conn
	 *            java.sql.Connection
	 */
	public static void release(ResultSet rs, Statement sta, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
				System.out.println("rs.close()");
			}
			rs = null;
		}

		if (sta != null) {
			try {
				sta.close();
			} catch (SQLException e) {
				e.printStackTrace();
				System.out.println("sta.close()");
			}
			sta = null;
		}

		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				System.out.println("conn.close()");
			}
			conn = null;
		}
	}
	

    public void exeSQL2(final String _sql)
    {
         this.getHiberanteTemplate().execute(new HibernateCallback() {
      			public Object doInHibernate(Session session) throws HibernateException,
      					SQLException {
      				Query query = session.createSQLQuery(_sql);
      				query.executeUpdate();
      				return null;
      			}
      		}) ;
    }
	
    @SuppressWarnings("unchecked")
    public List<T> querySQL2(final String _sql, final Class retClass, String _setSQL)
    {
    	List<Object> pojoList = null;
        Connection conn=null;  
        Statement stm=null;  
        ResultSet rs=null;  
        try {  
            conn=this.getHiberanteTemplate().getSessionFactory().openSession().connection();  
            stm = conn.createStatement();  
            if(_setSQL != null)
            {
            	stm.execute(_setSQL);
            }
            rs=stm.executeQuery(_sql);  
            ResultSetMapper resultSetMapper = new ResultSetMapper<Object>();
            pojoList = resultSetMapper.mapRersultSetToObject(rs, retClass);
            rs.close();
        } catch (HibernateException e) {  
            e.printStackTrace();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  catch (SecurityException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } finally{  
            try {  
//              if(null != rs){  
//                  rs.close();  
//              }  
                if(null != stm){  
                    stm.close();  
                }  
                if(null != conn){  
                    conn.close();  
                }  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }   
        return (List<T>)pojoList;
    }
	
	
	
}
